package service

import (
	"context"
	"errors"
	"golang.org/x/crypto/bcrypt"
	"webook/internal/domain"
	"webook/internal/repository"
	"webook/internal/repository/dao"
)

var (
	ErrUserDuplicateEmail    = dao.ErrUserDuplicateEmail
	ErrInvalidUserOrPassword = errors.New("账号/邮箱或密码不对")
)

type UserService struct {
	repo *repository.UserRepository
}

func NewUserService(repo *repository.UserRepository) *UserService {
	return &UserService{
		repo: repo,
	}
}

func (svc *UserService) SignUp(ctx context.Context, u domain.User) error {
	// 先加密密码
	hash, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	u.Password = string(hash)
	// 然后就是，存起来
	return svc.repo.Create(ctx, u)
}

func (svc *UserService) Login(ctx context.Context, email, password string) (domain.User, error) {
	// 先找用户
	u, err := svc.repo.FindByEmail(ctx, email)
	if err == repository.ErrUserNotFound {
		return domain.User{}, ErrInvalidUserOrPassword
	}
	if err != nil {
		return domain.User{}, err
	}
	// 比较密码了
	err = bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
	if err != nil {
		// DEBUG
		return domain.User{}, ErrInvalidUserOrPassword
	}
	return u, nil
}

func (svc *UserService) Edit(ctx context.Context, u domain.User) error {
	// 因为通过session 拿到了用户的id,所以不需要再去查找用户了,直接更新
	// 构造一个 map，包含要更新的字段及其新值
	updateFields := map[string]interface{}{
		"Nickname":     u.Nickname,
		"Birthday":     u.Birthday,
		"Introduction": u.Introduction,
	}
	return svc.repo.Update(ctx, u, updateFields)
}

func (svc *UserService) Profile(ctx context.Context, Id int64) (domain.User, error) {
	// 查找用户
	u, err := svc.repo.FindById(ctx, Id)
	return u, err
}
